/*
 * 
 */
package com.yuanmei.stockeyes.charts;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.PointF;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.View;
import android.view.View.OnTouchListener;

import com.tictactec.ta.lib.Core;
import com.tictactec.ta.lib.MAType;
import com.tictactec.ta.lib.MInteger;
import com.tictactec.ta.lib.RetCode;
import com.yuanmei.stockeyes.R;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import cn.limc.androidcharts.entity.DateValueEntity;
import cn.limc.androidcharts.entity.LineEntity;
import cn.limc.androidcharts.event.IDisplayCursorListener;
import cn.limc.androidcharts.view.SlipMinusLineChart;

//import android.util.Log;

public class TalibKdjChart implements ITalibChart {
    private final Core mTaLibCore = new Core();
    private Context mContext;
    private SlipMinusLineChart mKdjChartView;
    private static final String TAG = TalibKdjChart.class.getName();

    private List<DateValueEntity> mSlowKDateValueList;
    private List<DateValueEntity> mSlowDDateValueList;
    private List<DateValueEntity> mSlowJDateValueList;

    private LineEntity<DateValueEntity> mSlowKLineEntity;
    private LineEntity<DateValueEntity> mSlowDLineEntity;
    private LineEntity<DateValueEntity> mSlowJLineEntity;

    private int mKDJFastKPeriod = 9;
    private int mKDJSlowKPeriod = 3;
    private int mKDJSlowDPeriod = 3;
    private String mKDJSlowKPeriodName;
    private String mKDJFastKPeriodName;
    private String mKDJSlowDPeriodName;

    private int mTaIdxDataSetsBegin;
    private int mTaIdxDataSetsNumber;

    public TalibKdjChart(Context context) {
        mKdjChartView = new SlipMinusLineChart(context);
        TalibChartFactory.commonInitGridChart(mKdjChartView);
        TalibChartFactory.commonInitSlipLineChart(mKdjChartView);
        //TalibChartFactory.commonInitSlipStickChart(mKdjChartView);
        mContext =  mKdjChartView.getContext();
        mKDJFastKPeriodName = mContext.getString(R.string.param_kdj_fast_k_period);
        mKDJSlowKPeriodName = mContext.getString(R.string.param_kdj_slow_k_period);
        mKDJSlowDPeriodName = mContext.getString(R.string.param_kdj_slow_d_period);
    }

    @Override
    public List<Map<String, Object>> getTaParamsList() {

        List<Map<String, Object>> outParamsList = new ArrayList<Map<String, Object>>();
        Map<String, Object> item = new HashMap<String, Object>();
        item.put(ITalibChart.ITaParamNameKey,  mKDJFastKPeriodName);
        item.put(ITalibChart.ITaParamValueKey, mKDJFastKPeriod);
        outParamsList.add(item);

        item = new HashMap<String, Object>();
        item.put(ITalibChart.ITaParamNameKey,  mKDJSlowKPeriodName);
        item.put(ITalibChart.ITaParamValueKey, mKDJSlowKPeriod);
        outParamsList.add(item);

        item = new HashMap<String, Object>();
        item.put(ITalibChart.ITaParamNameKey,  mKDJSlowDPeriodName);
        item.put(ITalibChart.ITaParamValueKey, mKDJSlowDPeriod);
        outParamsList.add(item);

        return outParamsList;
    }

    @Override
    public void setTaParams(Hashtable<String, Integer> inParamMaps) {
         if (inParamMaps.containsKey(mKDJSlowKPeriodName)
                 && inParamMaps.containsKey(mKDJFastKPeriodName)
                 && inParamMaps.containsKey(mKDJSlowDPeriodName)
                 ) {
             mKDJSlowKPeriod = inParamMaps.get(mKDJSlowKPeriodName);
             mKDJFastKPeriod = inParamMaps.get(mKDJFastKPeriodName);
             mKDJSlowDPeriod = inParamMaps.get(mKDJSlowDPeriodName);
        }
    }

    @Override
    public boolean reloadData(int dataLen,
                              float[] openPrices,
                              float[] highPrices,
                              float[] lowPrices,
                              float[] closePrices,
                              float[] volumes,
                              float[] amounts,
                              int[] dates) {
        MInteger outBegIdx    = new MInteger();
        MInteger outNBElement = new MInteger();
        double[] outSlowK       = new double[dataLen];
        double[] outSlowD       = new double[dataLen];

//    public RetCode stoch(int startIdx, int endIdx,
//                         double[] inHigh, double[] inLow, double[] inClose,
//   int optInFastK_Period, int optInSlowK_Period, MAType optInSlowK_MAType, int optInSlowD_Period, MAType optInSlowD_MAType,
//          MInteger outBegIdx,  MInteger outNBElement, double[] outSlowK, double[] outSlowD)

        RetCode retCode = mTaLibCore.stoch(0, closePrices.length - 1,
                highPrices, lowPrices, closePrices,
                mKDJFastKPeriod, mKDJSlowKPeriod, MAType.T3, mKDJSlowDPeriod, MAType.T3,
                outBegIdx, outNBElement, outSlowK, outSlowD);
        if (retCode != RetCode.Success) {
            Log.e(TAG, "KDJ Chart mTaLibCore.stoch calc error retCode="
                    + retCode);
            return false;
        }

        mSlowKDateValueList = new ArrayList<>();
        mSlowDDateValueList = new ArrayList<>();
        mSlowJDateValueList = new ArrayList<>();
        for (int i = 0; i < dataLen; i++) {
            if (i < outBegIdx.value) {
                mSlowKDateValueList.add(new DateValueEntity(
                        (float) (outSlowK[0]), dates[i]));
                mSlowDDateValueList.add(new DateValueEntity(
                        (float) (outSlowD[0]), dates[i]));
                float slowJ = (float) (3*outSlowK[0] - 2*outSlowD[0]);
                mSlowJDateValueList.add(new DateValueEntity(
                        slowJ, dates[i]));
            } else {
                int idx = i - outBegIdx.value;
                mSlowKDateValueList.add(new DateValueEntity(
                        (float) (outSlowK[idx]), dates[i]));
                mSlowDDateValueList.add(new DateValueEntity(
                        (float) (outSlowD[idx]), dates[i]));
                float slowJ = (float) (3*outSlowK[idx] - 2*outSlowD[idx]);
                mSlowJDateValueList.add(new DateValueEntity(
                        slowJ, dates[i]));
            }
        }


        List<LineEntity<DateValueEntity>> lines = new ArrayList<>();

        mSlowKLineEntity = new LineEntity<>();
        mSlowKLineEntity.setTitle("K");
        mSlowKLineEntity.setLineColor(Color.WHITE);
        mSlowKLineEntity.setLineData(mSlowKDateValueList);
        lines.add(mSlowKLineEntity);

        mSlowDLineEntity = new LineEntity<>();
        mSlowDLineEntity.setTitle("D");
        mSlowDLineEntity.setLineColor(Color.YELLOW);
        mSlowDLineEntity.setLineData(mSlowDDateValueList);
        lines.add(mSlowDLineEntity);

        mSlowJLineEntity = new LineEntity<>();
        mSlowJLineEntity.setTitle("J");
        //mSlowJLineEntity.setLineColor(Color.RED);
        mSlowJLineEntity.setLineColor(mContext.getResources().getColor(R.color.fuchsia));
        mSlowJLineEntity.setLineData(mSlowJDateValueList);
        lines.add(mSlowJLineEntity);

        mKdjChartView.setLinesData(lines);

        mTaIdxDataSetsBegin  = outBegIdx.value;
        mTaIdxDataSetsNumber = outNBElement.value;
        return true;
    }

    @Override
    public int getTaIndexNumber() {
        return mTaIdxDataSetsNumber;
    }

    @Override
    public String getTaIndexParms() {
        return  mKDJFastKPeriod
                + "," + mKDJSlowKPeriod
                + "," + mKDJSlowDPeriod;
    }

    @Override
    public String getTaIndexShortName() {
        return "KDJ";
    }

    @Override
    public Spanned getTaIndexDetail() {
        if (null == mSlowKDateValueList || null == mSlowDDateValueList) {
            return new SpannableString("----");
        }
        int index = mKdjChartView.getSelectedIndex();

        DateValueEntity slowKEntity = mSlowKDateValueList.get(index);
        DateValueEntity slowDEntity = mSlowDDateValueList.get(index);
        DateValueEntity slowJEntity = mSlowJDateValueList.get(index);
        String slowKText = String.format(Locale.ENGLISH, "K:%.2f ", slowKEntity.getValue());
        String slowDText = String.format(Locale.ENGLISH, "D:%.2f ", slowDEntity.getValue());
        String slowJText = String.format(Locale.ENGLISH, "J:%.2f ", slowJEntity.getValue());

        String    finalString = slowKText + slowDText + slowJText;
        Spannable sb          = new SpannableString(finalString);

        sb.setSpan(new ForegroundColorSpan(mSlowKLineEntity.getLineColor()), finalString.indexOf(slowKText),
                finalString.indexOf(slowKText) + slowKText.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
        sb.setSpan(new ForegroundColorSpan(mSlowDLineEntity.getLineColor()), finalString.indexOf(slowDText),
                finalString.indexOf(slowDText) + slowDText.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
        sb.setSpan(new ForegroundColorSpan(mSlowJLineEntity.getLineColor()), finalString.indexOf(slowJText),
                finalString.indexOf(slowJText) + slowJText.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);

        return (sb);
    }

    @Override
    public int getTaIndexBegin() {
        return mTaIdxDataSetsBegin;
    }

    @Override
    public View getChartView() {
        return mKdjChartView;
    }

    @Override
    public void setDisplayFrom(int from) {
        mKdjChartView.setDisplayFrom(from);
    }

    @Override
    public void setDisplayCrossXOnTouch(boolean displayCrossXOnTouch) {
        mKdjChartView.setDisplayCrossXOnTouch(displayCrossXOnTouch);
    }

    @Override
    public void setDisplayNumber(int number) {
        mKdjChartView.setDisplayNumber(number);
    }

    @Override
    public void setOnTouchListener(OnTouchListener l) {
        mKdjChartView.setOnTouchListener(l);
    }

    @Override
    public void setOnDisplayCursorListener(
            IDisplayCursorListener l) {
        mKdjChartView.setOnDisplayCursorListener(l);
    }

    @Override
    public PointF getTouchPoint() {
        return mKdjChartView.getTouchPoint();
    }

    @Override
    public void setTouchPoint(PointF touchPoint) {
        mKdjChartView.setTouchPoint(touchPoint);
    }

    @Override
    public void postInvalidate() {
        mKdjChartView.postInvalidate();
    }

    @Override
    public float getValidMiddleY() {
        return mKdjChartView.getValidMiddleY();
    }
}
